﻿using DynORM.Interfaces;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace DynORM.BLLMapper
{
    public class PredicateConverter
    {
        //these ones mostly used from the above layers.
        //the Adapter itself uses Comparison instead of BLLComparison just because BLLComparison defines itself on MemberInfo 
        //and in Adapter we sometimes retrieve objects based on condition on fields that do not have corresponding MemberInfos.
        //for example in RetrieveFKObjsFromDB when we retrieve childs objects. we use db fields name convention to get children.
        public static ORMComparisonOperator BLLToORMComparisonOperator(BLLComparisonOperator bll_comparison_op)
        {
            switch (bll_comparison_op)
            {
                case BLLComparisonOperator.Equal:
                    return ORMComparisonOperator.Equal;
                case BLLComparisonOperator.Greater:
                    return ORMComparisonOperator.Greater;
                case BLLComparisonOperator.GreaterOrEqual:
                    return ORMComparisonOperator.GreaterOrEqual;
                case BLLComparisonOperator.Less:
                    return ORMComparisonOperator.Less;
                case BLLComparisonOperator.LessOrEqual:
                    return ORMComparisonOperator.LessOrEqual;

                //case BLLComparisonOperator.Like:
                //    return ORMComparisonOperator.Like;
                //case BLLComparisonOperator.In:
                //    return ORMComparisonOperator.In;
                case BLLComparisonOperator.NotEqual:
                    return ORMComparisonOperator.NotEqual;
                default:
                    return ORMComparisonOperator.Equal; //to satisfy compilator
            }
        }

        public static IORMComparison BLLToORMComparison(BLLComparison bll_comparison)
        {
            MemberInfo mi = bll_comparison.Member;
            string fieldName;
            if (mi.GetCustomAttributes(typeof(FieldAttribute), true).Any(p => p is FieldAttribute))
            {
                FieldAttribute fa = (FieldAttribute)mi.GetCustomAttributes(typeof(FieldAttribute), true).First();
                fieldName = (String.IsNullOrEmpty(fa.FieldName)) ? mi.Name : fa.FieldName;
            }
            else if (mi.GetCustomAttributes(typeof(PrimaryKeyAttribute), true).Any(p => p is PrimaryKeyAttribute))
            {
                PrimaryKeyAttribute fa = (PrimaryKeyAttribute)mi.GetCustomAttributes(typeof(PrimaryKeyAttribute), true).First();
                fieldName = (String.IsNullOrEmpty(fa.FieldName)) ? mi.Name : fa.FieldName;
            }
            else
                throw new Exception("Comparison should be described on a class member attributed with PrimaryKey or Field custom attribute.");

            return new Comparison(fieldName, BLLToORMComparisonOperator(bll_comparison.Condition), bll_comparison.Value);
        }

    }
}
